home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / util / cli / Sploin17.lha / Sploin.c next >
Encoding:
C/C++ Source or Header  |  1994-03-23  |  19.4 KB  |  814 lines

  1. /*
  2.     -------------------
  3.     ««« Sploin 1.70 »»»
  4.     -------------------
  5.     - Yves Perrenoud --
  6.     - 22.03.1994 ------
  7.     -------------------
  8. */
  9.  
  10. /* -------------------------Compilation notes--------------------------------
  11. **
  12. ** AMIGA
  13. ** -----
  14. ** This program should be compiled on the amiga using Matt Dillon great
  15. ** shareware compiler DICE. I haven't tried compiling it with SAS or Manx.
  16. ** In the next release, I will have tried compiling it with SAS 6.51 :-)
  17. **
  18. ** UNIX (SUN, Amix, MIPS)
  19. ** ----------------------
  20. ** I have only tested the program compiling it with cc (the default compiler).
  21. ** In a future release I will try compiling it with gcc.
  22. **
  23. ** VAX/VMS
  24. ** -------
  25. ** I compiled the program using VAXC under VMS 5.5-2.
  26. **
  27. */
  28.  
  29. /*
  30. ------------------------------------------------------------------------------
  31. ----------------------------------- History ----------------------------------
  32. ------------------------------------------------------------------------------
  33. -  V1.0  :  Base version, which only lets you extract and not really split,  -
  34. -           no bugs found.                                                   -
  35. ------------------------------------------------------------------------------
  36. -  V1.1  :  Added the option to split the file in x parts of a size          -
  37. -           specified by the user, or in a specified number of parts.        -
  38. ------------------------------------------------------------------------------
  39. -  V1.2  :  Added multi file join.                                           -
  40. ------------------------------------------------------------------------------
  41. -  V1.3  :  Added an option which tells Sploin to use an input file          -
  42. -           containing the names of files to join together. Removed a few    -
  43. -           little bugs.                                                     -
  44. ------------------------------------------------------------------------------
  45. -  V1.4  :  Wildcards are now supported. You can specify an destination dir. -
  46. -           when splitting in several parts.                                 -
  47. ------------------------------------------------------------------------------
  48. -  V1.45 :  Fixed an ugly bug which didn't accept subdirectories in the      -
  49. -           original path when using the -d option.                          -
  50. ------------------------------------------------------------------------------
  51. -  V1.5  :  Changed the program so it would no longer use the arp library    -
  52. -           for pattern matching and for break detection, but DICE routines  -
  53. -           instead. Also changed everything to Ansi-C (increased the binary -
  54. -           by 6k). Removed stupid options. Found bugs in the removed        -
  55. -           options (Hey hey!)                                               -
  56. ------------------------------------------------------------------------------
  57. -  V1.6  :  Added an option to reconstruct a previously split file.          -
  58. -           Corrected a bug in the input file option. Can now be compiled    -
  59. -           under UNIX.                                                      -
  60. ------------------------------------------------------------------------------
  61. -  V1.61 :  Fixed an Enforcer hit!                                           -
  62. ------------------------------------------------------------------------------
  63. -  V1.62 :  Changed the spliting size character from "$" to "=". The dollar  -
  64. -           sign is used by UNIX for specifying things like the last word    -
  65. -           on the previous line ("!$"). Due to this, on UNIX the program    -
  66. -           wouldn't split big files in smaller files of a specified size;   -
  67. -           which is my main use of the program.                             -
  68. ------------------------------------------------------------------------------
  69. -  V1.65 :  Removed a bug which didn't set the right protections on the      -
  70. -           created files under UNIX. Added VAX/VMS compatibility, but       -
  71. -           without wildcard support (until I find out how it works).        -
  72. ------------------------------------------------------------------------------
  73. -  V1.70 :  Added the "-m{l|h}" feature to greatly ease the transport on     -
  74. -           MS-DOS format disks by setting default sizes and truncating      -
  75. -           filenames to 8.3 chars when using the multiple file split/join   -
  76. -           options. Added the ']' in StripPath for VMS support.             -
  77. ------------------------------------------------------------------------------
  78. */
  79.  
  80. /* ---------------------------- To Do ----------------------------------------
  81. **
  82. ** 1. Add wildcards to VMS support and either optimize VMS open flags :-( or
  83. **    distribute the binary compiled with VMS GCC... whatever
  84. **
  85. ** 2. Strip all non uuencoded, VMS shared, shiped, etc... code from file(s)
  86. **    and create one file ready to be decoded.
  87. **
  88. */
  89.  
  90. #ifndef VAX
  91. #include <fcntl.h>
  92. #endif
  93.  
  94. #include <stdio.h>
  95. #include <stdlib.h>
  96. #include <string.h>
  97.  
  98. #ifdef VAX
  99. #include <unixlib.h>
  100. #include <file.h>
  101. #endif
  102.  
  103. #define Name "  «« Sploin 1.70 »»  Copyright (c) 1991-94  Yves Perrenoud\n"
  104.  
  105. #ifdef AMIGA
  106. static unsigned char *version_string = "$VER: Sploin 1.70 (22.03.94)";
  107. #endif
  108.  
  109. int hf1,hf2,hmain;                    /* les handles pour les 3 fichiers */
  110. FILE *hinp;                            /* le handle pour le fichier d'"input" */
  111.  
  112. unsigned char *memblock;            /* le pointeur sur la mémoire */
  113. size_t smain;                        /* la taille pour la mémoire en question */
  114.  
  115. unsigned char *inpmem;                /* le pointeur sur le inputfile */
  116.  
  117.  
  118. /* ------------------------------------------------------------------endprg
  119. ** Close open files and free memory.
  120. */
  121.  
  122. void endprg(val)
  123.     int val;
  124. {
  125.     if (hf1)
  126.         close(hf1);
  127.     if (hf2)
  128.         close(hf2);
  129.     if (hmain)
  130.         close(hmain);
  131.     if (hinp)
  132.         fclose(hinp);
  133.     if (memblock)
  134.         free(memblock);
  135.     if (inpmem)
  136.         free(inpmem);
  137.  
  138.     exit(val);
  139. }
  140.  
  141.  
  142. /* ------------------------------------------------------------------error
  143. ** In case of error output the string passed as an argument to
  144. ** the subroutine and call endprg with an exit code of 20.
  145. */
  146.  
  147. void error(msg,str)
  148.     char *msg,*str;
  149. {
  150.     printf("ERROR : %s%s!\n",msg,str);
  151.     endprg(20);
  152. }
  153.  
  154.  
  155. /* ------------------------------------------------------------------brk
  156. ** Jump to this subroutine in case the user has hit ^C.
  157. */
  158.  
  159. #ifdef AMIGA
  160. void brk()
  161. {
  162.     error("***BREAK","");
  163. }
  164. #endif
  165.  
  166.  
  167. /* ------------------------------------------------------------------GetConfirm
  168. ** Asks the user if it's ok to over write a file passed as an
  169. ** argument to the subroutine.
  170. */
  171.  
  172. int GetConfirm(filename)
  173.     char *filename;
  174. {
  175.     char buff[4];
  176.  
  177.     printf("\nDo you realy want to replace %s (y/N) : ",filename);
  178.  
  179.     fgets(buff,4,stdin);
  180.  
  181.     if ((buff[0] == 'y') || (buff[0] == 'Y'))
  182.         return 1;
  183.  
  184.     return 0;
  185. }
  186.  
  187.  
  188. /* ------------------------------------------------------------------GetSize
  189. ** Get the size of <filename>.
  190. */
  191.  
  192. int GetSize(filename)
  193.     char *filename;
  194. {
  195.     int hdsize;
  196.     int size;
  197.  
  198.     if ((hdsize = open(filename,O_RDONLY)) < 0)
  199.         error("Can't access file : ",filename);
  200.     
  201.     if ((size = lseek(hdsize,0,2)) < 0)
  202.         error("Can't examine file : ",filename);
  203.     
  204.     close(hdsize);
  205.     return size;
  206. }
  207.  
  208.  
  209. /* ------------------------------------------------------------------Copyright
  210. ** Output copyright message.
  211. */
  212.  
  213. void Copyright()
  214. {
  215.     puts(Name);
  216. }
  217.  
  218.  
  219. /* ------------------------------------------------------------------Message
  220. ** Output the help message.
  221. */
  222.  
  223. void Message()
  224. {
  225.     Copyright();
  226.  
  227.     puts("USAGE : Sploin <Mainfile> {<FileN>} [<options>]\n");
  228.  
  229.     puts("<Mainfile>  : The file to split or the joined file.");
  230.  
  231.     puts("<File1>     : The File in which to save the extracted data");
  232.     puts("              or the first file to be joined. Wildcards are supported.");
  233.  
  234.     puts("<File2>     : The file in which to save the rest of the splited file");
  235.     puts("              or the second file to be joined.\n");
  236.  
  237.     puts("[Options]");
  238.  
  239.     puts("-j          : Join File1,...,FileN into Mainfile.");
  240.  
  241.     puts("-sN         : Split Mainfile into File1 and optionaly File2.");
  242.     puts("              The N should be replaced either by a number which will");
  243.     puts("              represent the number of final files or if a = is present,");
  244.     puts("              the number following will be the size of the final files.\n");
  245.  
  246.     puts("-b<size>    : Buffer size (default 50000 bytes).");
  247.  
  248.     puts("-o<offst>   : Offset at which to start extracting data.");
  249.  
  250.     puts("-n<size>    : Number of bytes to extract.");
  251.  
  252.     puts("-r          : Saves what rests of the file after extraction (to EOF).");
  253.  
  254.     puts("-i<file>    : Tells Sploin to use <file> as input for the files to join.");
  255.  
  256.     puts("-g          : Reconstruct a file from the splited files (opposite of -sN).");
  257.  
  258.     puts("-d<dir>     : Specify the destination dir when spliting in several parts.");
  259.  
  260.     puts("-m{l|h}     : Use MS-DOS settings - filename size of 8.3 chars and disk");
  261.     puts("              size of l:720KB (DD) or h:1.44MB (HD).\n");
  262. }
  263.  
  264.  
  265. /* ------------------------------------------------------------------GetSep
  266. ** return the size of each individual chunk, when spliting a file
  267. ** in several little ones. If there is a = preceding the number, the
  268. ** number is the size itself. Otherwise, it represents the amount of
  269. ** chunks, so it's necessary to determine the size.
  270. */
  271.  
  272. int GetSep(arg)
  273.     char *arg;
  274. {
  275.     int nb;
  276.  
  277.     if (arg[2] == '=')
  278.         return atoi(&arg[3]);
  279.     else
  280.     {
  281.         nb = atoi(&arg[2]);
  282.         if (!(smain%nb))
  283.             return (smain/nb);
  284.         else
  285.             return (smain/nb + 1);
  286.     }
  287. }
  288.  
  289.  
  290. /* ------------------------------------------------------------------OpenF1
  291. ** Open file 1 for output with the name passed as an argument. Check
  292. ** if the file already exists and take the appropriate action if it
  293. ** does.
  294. */
  295.  
  296. void OpenF1(filename)
  297.     char *filename;
  298. {
  299.     if (Exists(filename))                            /* si le fichier existe */
  300.     {                                                   /* déja, alors on demande */
  301.         if (!GetConfirm(filename))                    /* une confirmation */
  302.             error("User aborted","");
  303.     }
  304.  
  305. #ifdef AMIGA
  306.     if ((hf1 = open(filename,O_WRONLY|O_CREAT)) < 0)
  307. #endif
  308.  
  309. #ifdef unix
  310.     if ((hf1 = open(filename,O_WRONLY|O_CREAT,600)) < 0)    /* 600 : owner RW */
  311. #endif
  312.  
  313. #ifdef VAX
  314.     if ((hf1 = open(filename,O_WRONLY|O_CREAT,0)) < 0)        /* 0 : default prot. */
  315. #endif
  316.         error ("Couldn't open file : ",filename);
  317. }
  318.  
  319.  
  320. /* ------------------------------------------------------------------StripPath
  321. ** Takes a filename with its path as input, and returns a pointer
  322. ** on a string containing the filename without its path.
  323. */
  324.  
  325. void *StripPath(bef)
  326.     char *bef;
  327. {
  328.     char aft[250];
  329.     int i,death=0;
  330.     
  331.     for (i=strlen(bef);death == 0;i--)
  332.     {
  333.         if ((bef[i] == ':') || (bef[i] == '/') || (bef[i] == ']') || (i < 0))
  334.             death = 1;
  335.     }
  336.  
  337.     if (i < 0)
  338.         strcpy(aft,bef);
  339.     else
  340.         strcpy(aft,&bef[i+2]);
  341.  
  342.     return((void *)aft);
  343. }
  344.  
  345.  
  346. /* ----------------------------------------------------------------Truncate
  347. ** returns a pointer on a filename in MS-DOS format consisting of
  348. ** 8.3 characters including a number passed as an argument in the
  349. ** following format <name>_1.{xxx}
  350. */
  351.  
  352. void *Truncate(full,num)
  353.     char *full;
  354.     int num;
  355. {
  356.     char trunc[250],anum[10];
  357.     int i,j,k;
  358.     
  359.     sprintf(anum,"%ld",num);
  360.     if (strlen(anum) > 4)
  361.         error("You have exceeded the maximum number of files possible in -m mode","");
  362.  
  363.     for (i=0;i < (8 - (1+strlen(anum)));i++)
  364.     {
  365.         switch (full[i])
  366.         {
  367.             case '.' :
  368.             case ' ' :
  369.                 trunc[i] = '_';
  370.                 break;
  371.             default :
  372.                 trunc[i] = full[i];
  373.                 break;
  374.         }
  375.     }
  376.  
  377.     trunc[i] = '\0';
  378.     sprintf(trunc,"%s_%s",trunc,anum);
  379.     k = strlen(trunc);
  380.  
  381.     for (i=strlen(full);(full[i] != '.') && (i >= 0);i--);
  382.  
  383.     if (i >= 0)
  384.     {
  385.         for(j=0;(j <= 3) && (j <= strlen(full)-i+1);j++)
  386.             trunc[k++] = full[j+i];
  387.         
  388.         trunc[k] = '\0';
  389.     }
  390.     return((void *)trunc);
  391. }
  392.  
  393.  
  394. /* ------------------------------------------------------------------Exists
  395. ** Check if a file already exists and return TRUE if it does, FALSE
  396. ** otherwise.
  397. */
  398.  
  399. int Exists(filename)
  400.     char *filename;
  401. {
  402.     int exhd;
  403.  
  404.     if ((exhd = open(filename,O_RDONLY)) >= 0)
  405.     {
  406.         close(exhd);
  407.         return 1;
  408.     }
  409.     else
  410.         return 0;
  411. }
  412.  
  413.  
  414. /* ------------------------------------------------------------------main
  415. ** The main routine.
  416. */
  417.  
  418. #ifdef AMIGA
  419. void main(xargc,xargv)
  420.     int xargc;
  421.     char **xargv;
  422. #else
  423. main(argc,argv)
  424.     int argc;
  425.     char **argv;
  426. #endif
  427. {
  428. #ifdef AMIGA
  429.     int argc;               /* les version expanded des arguments */
  430.     char **argv;            /* ceci est à supprimer sous UNIX et VMS */
  431. #endif
  432.  
  433.     int i,posi,                /* entier pour les boucles */
  434.  
  435.     type=1;                 /* type : 1 pour Join, 2 pour Split.
  436.                                Split : MaineFile   ->   File1 + File2
  437.                                Join  : File1 + File2   ->    MainFile */
  438.  
  439.     size_t bufsize=50000;    /* taille du buffer de travail, 50000 bytes*/
  440.  
  441.     int offset=0,            /* pour split, debut de l'extraction */
  442.  
  443.     size=0,                    /* taille à extraire */
  444.  
  445.     rest=0,                    /* Faut-il sauver le rebut après extraction?
  446.                                par défaut non. */
  447.  
  448.     inp=0,                    /* Faut-il utiliser un fichier comme input */
  449.  
  450.     group=0,                /* Faut-il regrouper des fichiers */
  451.     
  452.     msdos=0,                /* configuration MS-DOS */
  453.  
  454.     temp=0,endit=0,sep=0,        /* variable pour diverse utilisations */
  455.     allocsize=0,readsize=0,nbleft=0,total=0,iter=0;
  456.  
  457.     char Mainfile[250],File1[250],File2[250];    /* Fichier sus-mentionnés */
  458.     char path[250];            /* le répertoire de destination */
  459.     char Mainstriped[250];        /* le nom de fichier tronqué */
  460.  
  461. #ifdef AMIGA
  462.     if (expand_args(xargc,xargv,&argc,&argv))        /* expand arguments */
  463.         error("Couldn't expand arguments","");
  464.  
  465.     onbreak(brk);            /* if a ^C is detected jump to brk */
  466. #endif
  467.  
  468.     if (argc < 3)
  469.     {
  470.         Message();
  471.         error("Not enough arguments","");
  472.     }
  473.  
  474.     Mainfile[0] = '*';
  475.     File1[0] = '*';
  476.     File2[0] = '*';
  477.     path[0] = '*';
  478.         
  479.     for (i=1;i <= (argc-1);i++)
  480.     {
  481.         if (argv[i][0] == '-')
  482.         {
  483.             switch (argv[i][1])
  484.             {
  485.                 case 'j' : type = 1; break;
  486.                 case 's' : type = 2; sep = (argv[i][2] != 0) ? i : 0; break;
  487.                 case 'b' : bufsize = atoi(&argv[i][2]); break;
  488.                 case 'o' : offset = atoi(&argv[i][2]); break;
  489.                 case 'n' : size = atoi(&argv[i][2]); break;
  490.                 case 'r' : rest = 1; break;
  491.                 case 'i' : inp = 1; strcpy(File2,&argv[i][2]); break;
  492.                 case 'd' : strcpy(path,&argv[i][2]); break;
  493.                 case 'g' : group = 1; break;
  494.                 case 'm' : msdos = 1; sep = (argv[i][2] == 'h') ? 1456000 : 728000; break;
  495.                 default  : error("Uknown type of OPTION","");
  496.             }
  497.         }
  498.         else if (Mainfile[0] == '*')
  499.         {
  500.             strcpy(Mainfile,argv[i]);
  501.             posi = i;
  502.         }
  503.         else if (File1[0] == '*')
  504.             strcpy(File1,argv[i]);
  505.         else if (File2[0] == '*')
  506.             strcpy(File2,argv[i]);
  507.     }
  508.  
  509.     if ((sep != 0) || (type == 1))
  510.     {
  511.         offset = 0;
  512.         size = 0;
  513.         rest = 0;
  514.  
  515.         if (Mainfile[0] == '*')
  516.             error("You must specify all the filenames","");
  517.     }
  518.     else if ((Mainfile[0] == '*') || (File1[0] == '*') || ((rest == 1) && (File2[0] == '*')))
  519.         error("You must specify all the filenames","");
  520.  
  521.     strcpy(Mainstriped,StripPath(Mainfile));    /* on extrait le nom lui-même */
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529. /* First of all the Join part of the program */
  530.  
  531.     if (type == 1)
  532.     {
  533.         Copyright();
  534.         printf("Joining the files into %s ...\n",Mainfile);
  535.  
  536.         if (Exists(Mainfile))                            /* si le fichier existe */
  537.         {                                                /* déja, alors on demande */
  538.             if (!GetConfirm(Mainfile))                    /* une confirmation */
  539.                 error("User aborted","");
  540.         }
  541.  
  542. #ifdef AMIGA
  543.         if ((hmain = open(Mainfile,O_WRONLY|O_CREAT)) < 0)
  544. #endif
  545.  
  546. #ifdef unix
  547.         if ((hmain = open(Mainfile,O_WRONLY|O_CREAT,600)) < 0)    /* 600 : owner RW */
  548. #endif
  549.  
  550. #ifdef VAX
  551.         if ((hmain = open(Mainfile,O_WRONLY|O_CREAT,0)) < 0)    /* 0 : default prot. */
  552. #endif
  553.             error ("Couldn't open file : ",Mainfile);
  554.  
  555.         if (!(memblock = calloc(bufsize,1)))
  556.             error("Not enough memory, reduce buffer size","");
  557.  
  558.         if (inp)
  559.         {
  560.             if (!(hinp = fopen(File2,"r")))
  561.                 error("Couldn't open input file : ",File2);
  562.  
  563.             if (feof(hinp))
  564.                 error("Input file is empty","");
  565.         }
  566.  
  567.         i = posi;
  568.         posi = 1;
  569.  
  570.         while (!total)
  571.         {
  572. #ifdef AMIGA
  573.             chkabort();            /* check if a ^C was pressed */
  574. #endif
  575.  
  576.             if (inp)
  577.             {
  578.                 /* taking the next file from the input file */
  579.  
  580.                 if (fgets(File1,255,hinp))            /* get the line */
  581.                 {
  582.                     size = strlen(File1);
  583.                     File1[size-1] = '\0';            /* remove the \n */
  584.                 }
  585.                 else
  586.                 {
  587.                     total = 1;                /* if we have reached the end of file */
  588.                     continue;
  589.                 }
  590.             }
  591.             else if (group)
  592.             {
  593.                 /* reconstruct a file splited with -sxxxx */
  594.                 
  595.                 strcpy(File1,Truncate(Mainstriped,posi));
  596.  
  597.                 if (!Exists(File1))
  598.                 {
  599.                     sprintf(File1,"%s_%ld",Mainstriped,posi);
  600.  
  601.                     if (!Exists(File1))
  602.                     {
  603.                         total = 1;
  604.                         continue;
  605.                     }
  606.                 }
  607.                 
  608.                 posi++;
  609.             }
  610.             else
  611.             {
  612.                 i++;                            /* go to next entry */
  613.  
  614.                 if (i > (argc-1))
  615.                 {
  616.                     total = 1;
  617.                     continue;
  618.                 }
  619.  
  620.                 if (argv[i][0] != '-')
  621.                     strcpy(File1,argv[i]);
  622.                 else
  623.                     continue;
  624.             }
  625.  
  626.             if ((hf1 = open(File1,O_RDONLY)) < 0)
  627.                 error("Couldn't open file : ",File1);
  628.  
  629.             do
  630.             {
  631.                 if((temp = read(hf1,memblock,bufsize)) < 0)
  632.                     error("Couldn't read file ",File1);
  633.  
  634.                 if (temp != bufsize)
  635.                     endit = 1;
  636.                 else
  637.                     temp = bufsize;
  638.  
  639.                 if(write(hmain,memblock,temp) < 0)
  640.                     error("Couldn't write into file ",Mainfile);
  641.             }
  642.             while (!endit);
  643.             endit = 0;
  644.  
  645.             close(hf1);
  646.             hf1 = 0;
  647.         }
  648.     }
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658. /* Here comes the Split part of the program */
  659.  
  660.     else
  661.     {
  662.         Copyright();
  663.         printf("Spliting %s ",Mainfile);
  664.  
  665.         if (rest)
  666.             printf("into %s and %s ...\n",File1,File2);
  667.         else if (sep != 0)
  668.             puts("...");
  669.         else
  670.             printf("into %s ...\n",File1);
  671.  
  672.         if ((hmain = open(Mainfile,O_RDONLY)) < 0)
  673.             error("Couldn't open file : ",Mainfile);
  674.  
  675.         smain = GetSize(Mainfile);
  676.         if (sep && (!msdos))
  677.             sep = GetSep(&argv[sep][0]);
  678.  
  679.         if (sep == 0)
  680.         {
  681.             if ((offset+size) > smain)
  682.                 error("Can't extract more bytes than the file contains","");
  683.  
  684.             OpenF1(File1);
  685.  
  686.             if (rest)
  687.             {
  688.                 if (Exists(File2))                        /* si le fichier existe */
  689.                 {                                        /* déja, alors on demande */
  690.                     if (!GetConfirm(File2))                /* une confirmation */
  691.                         error("User aborted","");
  692.                 }
  693.  
  694. #ifdef AMIGA
  695.                 if ((hf2 = open(File2,O_WRONLY|O_CREAT)) < 0)
  696. #endif
  697.  
  698. #ifdef unix
  699.                 if ((hf2 = open(File2,O_WRONLY|O_CREAT,600)) < 0)    /* 600 : owner RW */
  700. #endif
  701.  
  702. #ifdef VAX
  703.                 if ((hf2 = open(File2,O_WRONLY|O_CREAT,0)) < 0)    /* 0 : default prot. */
  704. #endif
  705.                     error ("Couldn't open file : ",File2);
  706.             }
  707.  
  708.             allocsize = rest ? smain-offset : size;
  709.             iter = 1;
  710.         }
  711.         else
  712.         {
  713.             allocsize = sep;
  714.             if (allocsize < bufsize)
  715.                 bufsize = allocsize;
  716.             if (smain%sep)
  717.                 iter = (smain/sep) + 1;
  718.             else
  719.                 iter = smain/sep;
  720.         }
  721.  
  722.         if (bufsize == 0)
  723.             bufsize = allocsize;
  724.  
  725.         if (!(memblock = calloc(bufsize,1)))
  726.             error("Not enough memory, reduce buffer size","");
  727.  
  728.         if (offset)
  729.         {
  730.             if (lseek(hmain,offset,0) < 0)
  731.                 error("Couldn't browse through file ",Mainfile);
  732.         }
  733.  
  734.         for (i=1;i <= iter;i++)
  735.         {
  736. #ifdef AMIGA
  737.             chkabort();
  738. #endif
  739.  
  740.             if (sep != 0)
  741.             {
  742.                 if (hf1)
  743.                     close(hf1);
  744.  
  745.                 total += sep;
  746.                 if (total > smain)
  747.                     nbleft = smain%sep;
  748.                 else
  749.                     nbleft = sep;
  750.  
  751.                 if (msdos)
  752.                 {
  753.                     if (path[0] == '*')
  754.                         strcpy(File1,Truncate(Mainfile,i));
  755.                     else
  756.                         sprintf(File1,"%s%s",path,Truncate(Mainstriped,i));
  757.                 }
  758.                 else
  759.                 {
  760.                     if (path[0] == '*')
  761.                         sprintf(File1,"%s_%ld",Mainfile,i);
  762.                     else
  763.                         sprintf(File1,"%s%s_%ld",path,Mainstriped,i);
  764.                 }
  765.                 OpenF1(File1);
  766.             }
  767.             else
  768.                 nbleft = size;
  769.  
  770.             do
  771.             {
  772.                 if (nbleft < bufsize)
  773.                 {
  774.                     readsize = nbleft;
  775.                     endit = 1;
  776.                 }
  777.                 else
  778.                     readsize = bufsize;
  779.  
  780.                 if(read(hmain,memblock,readsize) < 0)
  781.                     error("Couldn't read file ",Mainfile);
  782.  
  783.                 if(write(hf1,memblock,readsize) < 0)
  784.                     error("Couldn't write into file ",File1);
  785.  
  786.                 nbleft -= bufsize;
  787.             }
  788.             while (!endit);
  789.             endit = 0;
  790.         }
  791.  
  792.         if (rest)
  793.         {
  794.             do
  795.             {
  796.                 if((temp = read(hmain,memblock,bufsize)) < 0)
  797.                     error("Couldn't read file ",Mainfile);
  798.  
  799.                 if (temp != bufsize)
  800.                     endit = 1;
  801.                 else
  802.                     temp = bufsize;
  803.  
  804.                 if(write(hf2,memblock,temp) < 0)
  805.                     error("Couldn't write into file ",Mainfile);
  806.             }
  807.             while (!endit);
  808.         }
  809.     }
  810.  
  811.     puts("Done.");
  812.     endprg(0);
  813. }
  814.